home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
libs
/
usergrouplib.lha
/
usergroup
/
credential.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-02
|
20KB
|
759 lines
RCS_ID_C="$Id: credential.c,v 4.2 1994/05/18 15:43:02 ppessi Exp $";
/*
* credential.c --- handle credentials
*
* Author: ppessi <Pekka.Pessi@hut.fi>
*
* This file is part of the AmiTCP/IP User Library.
*
* Copyright © 1993 AmiTCP/IP Group, <AmiTCP-Group@hut.fi>
* Helsinki University of Technology, Finland.
*
* Created : Wed Sep 15 01:25:26 1993 ppessi
* Last modified: Wed May 18 18:42:43 1994 ppessi
*/
#include "base.h"
#include "credential.h"
#include "libfunc.h"
#include <exec/memory.h>
#include <exec/alerts.h>
#include <string.h>
#include <assert.h>
struct CredentialResource *CredentialBase;
#ifdef notyet
typedef struct CredentialResource *(*resident_init_fp)(void);
/*
* Create credential resource
*/
struct CredentialResource *CredentialInit(const char *name)
{
BPTR resseg = LoadSeg(_PATH_CREDENTIAL);
if (resseg) {
resident_init_fp initf = (resident_init_fp)((LONG *)(resseg << 2) + 1);
struct CredentialResource *res = initf();
if (res)
return res;
UnLoadSeg(resseg);
}
return NULL;
}
#endif
/****** usergroup.library/getspgrp ********************************************
NAME
getpgrp - get process group identification
SYNOPSIS
#include <libraries/usergroup.h>
sessionid = getpgrp()
D0
pid_t getpgrp(void);
FUNCTION
The getpgrp() function returns the process group id for the current
process. Currently, the process group ID is the same as the session
ID. The 0 is valid process group ID for console session.
RESULTS
Upon successful completion, the value of the process group ID is
returned. Otherwise, a value of -1 is returned and an error code is
stored to global errno location.
ERRORS
[ESRCH] The calling process don't belong to any process group.
SEE ALSO
setsid(), exec.library/FindTask()
******************************************************************************
*/
SAVEDS ASM pid_t R_getpgrp(void)
{
struct proc *p = procfind(NULL);
return p->p_session->s_leader;
}
/****** usergroup.library/setsid *********************************************
NAME
setsid - create a new session
SYNOPSIS
#include <unistd.h>
sessionid = setsid()
D0
pid_t setsid(void);
FUNCTION
The setsid() function creates a new session when the calling
process is not a process group leader. The calling process
then becomes the session leader of this session and the only
process in the new session.
RESULTS
Upon successful completion, the value of the new session ID is
returned. Otherwise, a value of -1 is returned and an error
code is stored to global errno location.
ERRORS
[EPERM] The calling process is already a session leader.
SEE ALSO
getpgrp()
******************************************************************************
*/
SAVEDS ASM pid_t R_setsid(void)
{
#ifdef notyet
pid_t pid = (pid_t)FindTask(NULL);
struct proc *p = procfind(pid);
int error;
if (p->p_session->s_leader == pid) {
error = EPERM;
} else {
struct session *session;
while (!(session = AllocMem(sizeof(*session), MEMF_CLEAR|MEMF_PUBLIC))) {
Alert(AG_NoMemory | UG_CredRes);
Wait(0L);
}
InitList((struct List *)session->s_pgrpl);
Forbid();
p = proccopy(p, pid);
p->p_ucred->cr_ref++;
p->p_ucred = crcopy(p->p_ucred);
/* Remove from old process group */
rempgrp(p);
p->p_session = session;
MinAddHead(session->s_pgrpl, p->p_pgrp);
session->s_consoletask = GetConsoleTask();
session->s_leader = pid;
Permit();
return pid;
}
SetErrno(error);
return -1;
#endif
return 0;
}
#ifdef notyet
/*
* Remove a process from session's process group and
* free session if last process is removed
*/
void
rempgrp(struct proc *p)
{
Forbid();
/* Free the session structure if the last task in process group dies */
MinRemove((struct Node *)p->p_pgrp);
if (IsMinListEmpty(p->p_session->s_pgrpl)) {
FreeMem(p->p_session, sizeof(*p->p_session));
} else if (p->p_session->s_leader == (pid_t)p->p_task) {
}
Permit();
}
#endif
/*
* Check super-user
*/
int
suser(struct ucred *cred)
{
if (cred->cr_uid == 0)
return 0;
return EPERM;
}
/*
* Search credentials
*/
static struct pcred *crfind(pid_t pid)
{
return procfind(pid)->p_cred;
}
/****** usergroup.library/getuid *********************************************
NAME
getuid, geteuid - get user process identification
getgid, getegid - get group process identification
SYNOPSIS
ruid = getuid()
D0
uid_t getuid(void);
euid = geteuid()
D0
uid_t geteuid(void);
rgid = getgid()
D0
gid_t getgid(void);
egid = getegid()
D0
gid_t getegid(void);
FUNCTION
The getuid() function returns the real user ID of the calling
process, geteuid() returns the effective user ID of the calling
process.
The getgid() function returns the real group ID of the calling
process, getegid() returns the effective group ID of the calling
process.
The real user ID and real group ID is specified at login time.
The real ID is the ID of the user who invoked the program. As the
effective user and gourp ID gives the process additional permissions
during the execution of `set-user-ID' or `set-group-ID' mode
programs, functions getgid() and getuid () are used to determine the
real-ids of the calling process.
RESULT
The getuid(), geteuid(), getgid(), and getegid() functions are
always successful, and no return value is reserved to indicate an
error.
NOTES
Any task can call these functions
SEE ALSO
getgroups(), setuid(), setreuid(), setgid(), setregid(), setgroups()
******************************************************************************
*/
SAVEDS ASM uid_t R_getuid(void)
{
return crfind(NULL)->p_ruid;
}
SAVEDS ASM uid_t R_geteuid(void)
{
return crfind(NULL)->p_euid;
}
SAVEDS ASM gid_t R_getgid(void)
{
return crfind(NULL)->p_rgid;
}
SAVEDS ASM gid_t R_getegid(void)
{
return crfind(NULL)->p_egid;
}
/****** usergroup.library/getgroups *******************************************
NAME
getgroups - get group access list
SYNOPSIS
len = getgroups(gidsetlen, gidset[])
D0 D0 A0
int getgroups(int, gid_t *);
FUNCTION
Getgroups() gets the current group access list of the user process
and stores it in the array gidset. The parameter gidsetlen indicates
the number of entries that may be placed in gidset. The function
getgroups() returns the actual number of groups returned in gidset.
No more than NGROUPS, as defined in <libraries/usergroup.h>, will
ever be returned.
RESULT
A successful call returns the number of groups in the group set. A
value of -1 indicates that the argument gidsetlen is smaller than
the number of groups in the group set.
ERRORS
[EINVAL] The argument gidsetlen is smaller than the number of
groups in the group set.
[EFAULT] The argument gidset specifies an invalid address.
SEE ALSO
setgroups(), initgroups(), getgid(), getegid()
HISTORY
The getgroups function call appeared in 4.2BSD.
****************************************************************************
*/
SAVEDS ASM int R_getgroups(REG(d0) int ngroups, REG(a1) gid_t *groups)
{
struct pcred *pc = crfind(NULL);
gid_t *getgroups;
short error;
if (ngroups == 0) {
return pc->p_ngroups;
} else if (ngroups < pc->p_ngroups) {
error = EINVAL;
} else if (groups == NULL || ((LONG)groups & 1) != 0) {
error = EFAULT;
} else {
/* This does also UWORD -> gid_t conversion */
getgroups = pc->p_groups;
ngroups = pc->p_ngroups;
while (ngroups-- > 0) {
*groups++ = *getgroups++;
}
return pc->p_ngroups;
}
SetErrno(error);
return -1;
}
/****** usergroup.library/setuid ***********************************************
NAME
setuid, setreuid - set real and effective user ID's
setgid, setregid - set real and effective group ID's
SYNOPSIS
success = setuid(uid)
D0 D0
int setuid(uid_t);
success = setreuid(ruid, euid);
D0 D0 D1
int setreuid(uid_t, uid_t);
success = setgid(gid)
D0 D0
int setgid(gid_t);
success = setregid(ruid, euid)
D0 D0 D1
int setregid(gid_t ruid, gid_t euid);
FUNCTION
The real and effective ID's of the current process are set according
to the arguments. If ruid or euid is -1, the current uid is filled
in by the system. Unprivileged users may change the real ID to the
effective ID and vice-versa; only the super-user may make other
changes.
RETURN VALUES
Upon successful completion, a value of 0 is returned. Otherwise, a
value of -1 is returned and errno is set to indicate the error.
ERRORS
[EPERM] The current process is not the super-user and a change
other than changing the effective id to the real id was
specified.
SEE ALSO
getuid(), getgid(), geteuid(), getegid()
NOTES
Any task can call these functions.
HISTORY
A setuid() and setgid() function calls appeared in Version 6 AT&T
UNIX. The setreuid() and setregid() function calls appeared in
4.2BSD.
****************************************************************************
*/
SAVEDS ASM int R_setuid(REG(d0) uid_t uid)
{
return R_setreuid(uid, uid);
}
SAVEDS ASM int R_setreuid(REG(d0) uid_t ruid, REG(d1) uid_t euid)
{
struct pcred *pc = crfind(NULL);
short error;
if (ruid == NOID)
ruid = pc->p_ruid;
if (euid == NOID)
euid = pc->pc_ucred->cr_uid;
/*
* Allow setting real uid to previous effective, for swapping real and
* effective. This should be:
*
* if (ruid != pc->p_ruid &&
* (error = suser(pc->pc_ucred, &p->p_acflag)))
*/
#if 1
/* allow setreuid(-1, 0) to emulate SUID */
if ((ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
(error = suser(pc->pc_ucred))) ||
(/* euid != pc->pc_ucred->cr_uid */ 0 && euid != pc->p_ruid &&
(error = suser(pc->pc_ucred))))
#else
if ((ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
(error = suser(pc->pc_ucred))) ||
(euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
(error = suser(pc->pc_ucred))))
#endif
{
unlock(&credential_list);
SetErrno(error);
return -1;
} else {
/*
* Everything's okay, do it. Copy credentials so other references do
* not see our changes.
*/
pc->pc_ucred = crcopy(pc->pc_ucred);
pc->pc_ucred->cr_uid = euid;
pc->p_ruid = ruid;
return 0;
}
}
SAVEDS ASM int R_setgid(REG(d0) gid_t gid)
{
return R_setregid(gid, gid);
}
SAVEDS ASM int R_setregid(REG(d0) gid_t rgid, REG(d1) gid_t egid)
{
struct pcred *pc = crfind(NULL);
short error;
if (rgid == NOID)
rgid = pc->p_rgid;
if (egid == NOID)
egid = pc->pc_ucred->cr_gid;
/*
* Allow setting real gid to previous effective, for swapping real and
* effective. This should be:
*
* if (rgid != pc->p_rgid &&
* (error = suser(pc->pc_ucred, &p->p_acflag)))
*/
if ((rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_gid /* XXX */ &&
(error = suser(pc->pc_ucred))) ||
(egid != pc->pc_ucred->cr_gid && egid != pc->p_rgid &&
(error = suser(pc->pc_ucred)))) {
SetErrno(error);
return -1;
} else {
/*
* Everything's okay, do it. Copy credentials so other references do
* not see our changes.
*/
pc->pc_ucred = crcopy(pc->pc_ucred);
pc->pc_ucred->cr_gid = egid;
pc->p_rgid = rgid;
return 0;
}
}
/****** usergroup.library/setgroups ******************************************
NAME
setgroups - set group access list
SYNOPSIS
success = setgroups(ngroups, gidset)
D0 D0 A0
int setgroups(int, const gid_t *);
FUNCTION
Setgroups() sets the group access list of the current user process
according to the array gidset. The parameter ngroups indicates the
number of entries in the array and must be no more than NGROUPS, as
defined in <libraries/usergroup.h>.
Only the super-user may set new groups. The super-user can not
set illegal groups (-1).
RESULT
A 0 value is returned on success, -1 on error, with an error
code stored in errno and available with ug_GetErr() function.
ERRORS
[EINVAL] An illegal group id was specified.
[EPERM] The caller has got no necessary privileges.
[EFAULT] The address specified for gidset is illegal.
NOTES
Any task can call this function.
SEE ALSO
getgroups(), initgroups()
****************************************************************************
*/
SAVEDS ASM int R_setgroups(REG(d0) int ngrp,
REG(a1) const gid_t *groups)
{
register struct pcred *pc = crfind(NULL);
register gid_t *gp;
register const gid_t *lp;
short error;
if (error = suser(pc->pc_ucred /*, &p->p_acflag */)) {
} else if (ngrp > NGROUPS) {
error = EINVAL;
} else if (groups == NULL || ((LONG)groups & 1) != 0) {
error = EFAULT;
} else {
pc->pc_ucred = crcopy(pc->pc_ucred);
pc->pc_ucred->cr_ngroups = ngrp;
for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
*gp++ = *lp++;
return 0;
}
SetErrno(error);
return -1;
}
/****** usergroup.library/MU2UG **********************************************
NAME
MU2ID - macro converting MultiUser id to usergroup id
ID2MU - macro converting usergroup id to MultiUser id
SYNOPSIS
ug_id = MU2ID(mu_id)
mu_id = ID2MU(ug_id)
FUNCTION
These macros are used to convert between different user ID
formats. The mu_id is in the format used by MultiUser filesystem
and multiuser.library. The ug_id is the format used by Unix and
usergroup.library.
Most of the id values are identical in usergroup.library and
multiuser.library. However, these two exceptions have values as
follows:
usergroup.library multiuser.library
super-user 0 65535
nobody -2 0
INPUTS AND RESULTS
mu_id - user ID in MultiUser format.
ug_id - user ID in usergroup format.
BUGS
The usergroup id values that won't fit into UWORD are truncated.
SEE ALSO
******************************************************************************
*/
#if 0
ASM uid_t R_ug_mu2id(REG(d0) UWORD id)
{
if (id == 0) {
return -2;
} else if (id == 65535) {
return 0;
} else {
return id;
}
}
ASM UWORD R_ug_id2mu(REG(d0) uid_t id)
{
if (id == 0) {
return 65535;
} else if (id == -2) {
return 0;
} else {
return id;
}
}
#endif
/****** usergroup.library/umask *********************************************
NAME
umask - set file creation mode mask
SYNOPSIS
#include <sys/stat.h>
oldmask = umask(newmask)
D0 D0
mode_t umask(mode_t);
FUNCTION
The umask() routine sets the process's file mode creation mask to
numask and returns the previous value of the mask. The 9 low-order
access permission bits of numask are used by Unix-compatible
filesystems, for examble by NFS, to turn off corresponding bits
requested in file mode. This clearing allows each user to restrict
the default access to his files.
The default mask value is 022 (write access for owner only). Child
processes should inherit the mask of the calling process.
RESULT
The previous value of the file mode mask is returned by the call.
ERRORS
The umask() function is always successful.
SEE ALSO
getumask()
******************************************************************************
*/
SAVEDS ASM mode_t R_umask(REG(d0) mode_t newmask)
{
struct proc *p = procfind(NULL);
mode_t oldmask = p->p_umask;
p->p_umask = newmask;
return oldmask ;
}
/****** usergroup.library/getumask *********************************************
NAME
getumask - get file creation mode mask
SYNOPSIS
#include <sys/stat.h>
oldmask = getumask()
D0
mode_t getumask(void);
FUNCTION
The getumask() routine sets the process's file mode creation mask to
numask and returns the previous value of the mask. The 9 low-order
access permission bits of numask are used by Unix-compatible
filesystems, for examble by NFS, to turn off corresponding bits
requested in file mode.
RESULT
The value of the file mode mask is returned by the call.
ERRORS
The getumask() function is always successful.
SEE ALSO
umask()
******************************************************************************
*/
SAVEDS ASM mode_t R_getumask(void)
{
struct proc *p = procfind(NULL);
return p->p_umask;
}
/****** usergroup.library/getcredentials *************************************
NAME
getcredentials -- get credentials of given task. (V4)
SYNOPSIS
#include <libraries/usergroup.h>
credentials = getcredentials(task)
D0 A0
struct UserGroupCredentials *getcredentials(struct Task *);
FUNCTION
The function getcredentials() returns all credentials of the given
task. The credentials include real and effective user and group IDs,
umask, login name and session ID. If the task pointer is NULL, the
credentials of current task are returned.
RESULT
A getcredentials() function returns a valid pointer to structure
UserGroupCredentials on success and a null pointer if an error
occurs.
ERRORS
[EINVAL] An illegal task pointer was specified.
BUGS
This function leave its result in an internal static object and
return a pointer to that object. Subsequent calls to this function
will modify the same object.
SEE ALSO
******************************************************************************
*/
static struct UserGroupCredentials creds[1];
SAVEDS ASM struct UserGroupCredentials
*R_getcredentials(REG(a0) struct Task *task)
{
register struct proc *p = procfind(task);
if (p != NULL) {
register struct UserGroupCredentials *c = creds;
c->cr_ruid = p->p_cred->p_ruid;
c->cr_rgid = p->p_cred->p_rgid;
c->cr_umask = p->p_umask;
c->cr_euid = p->p_cred->p_euid;
c->cr_ngroups = p->p_cred->p_ngroups;
c->cr_session = p->p_session->s_leader;
memcpy(c->cr_groups, p->p_cred->p_groups, sizeof(c->cr_groups));
memcpy(c->cr_login, p->p_session->s_login, sizeof(c->cr_login));
return c;
}
return NULL;
}